package redis

import (
	"errors"
	"fmt"
	"github.com/gomodule/redigo/redis"
	uuid "github.com/satori/go.uuid"
	"session"
	"sync"
	"time"
)

// 实现 Session_Manager 的接口
// RedisSessionManager
type RedisSessionManager struct {
	addr       string // redis地址
	password   string // 密码
	pool       *redis.Pool
	rwlock     sync.RWMutex
	sessionMap map[string]session.Session // 存放 session 的 map
}

// NewRedisSessionManager 构造函数
func NewRedisSessionManager() session.SessionManager {
	return &RedisSessionManager{
		sessionMap: make(map[string]session.Session, 32),
	}
}

// Init
func (r RedisSessionManager) Init(addr string, option ...interface{}) (err error) {
	// 判断是否多个参数
	if len(option) > 0 {
		r.password = fmt.Sprint(option[0])
	}
	r.addr = addr
	r.pool = myPool(addr, r.password) // 创建连接池
	return
}

// 创建连接池
func myPool(addr string, password string) *redis.Pool {
	return &redis.Pool{
		MaxIdle:     64,
		MaxActive:   1000,
		IdleTimeout: time.Second * 240,
		Dial: func() (redis.Conn, error) {
			conn, err := redis.Dial("tcp", addr)
			if err != nil {
				return nil, err
			}
			// 若有密码
			if _, err := conn.Do("AUTH", password); err != nil {
				_ = conn.Close()
				return nil, err
			}
			return conn, err
		},
		// 链接测试，开发时用，上线时注释
		TestOnBorrow: func(c redis.Conn, t time.Time) error {
			_, err := c.Do("PING")
			return err
		},
	}
}

// CreateSession
func (r RedisSessionManager) CreateSession() (session session.Session, err error) {
	// 加锁
	r.rwlock.Lock()
	defer r.rwlock.Unlock()
	// 用 uuid 作为 sessionId
	// go get github.com/satori/go.uuid
	uid := uuid.NewV4()
	sessionID := uid.String()
	session = NewRedisSession(sessionID, r.pool) // 创建 RedisSession
	r.sessionMap[sessionID] = session            // 吧 RedisSession 放入到大的Map中
	return
}

// Get
func (r RedisSessionManager) Get(sessionId string) (session session.Session, err error) {
	// 加锁
	r.rwlock.Lock()
	defer r.rwlock.Unlock()
	// 取值
	session, ok := r.sessionMap[sessionId]
	if !ok {
		err = errors.New("session not exists")
		return
	}
	return
}
